using System;
using System.Linq;
using System.Xml.Linq;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;

namespace BareWeb.FluentAzureDiagnostics
{
    public class AzureBlobStorage : IAzureBlobStorage
    {
        private readonly CloudStorageAccount _cloudStorageAccount;
        private readonly string _deploymentId;
        private readonly string _roleName;
        private readonly string _filename;
        private const string CloudContainerName = "wad-control-container";
        private const string CloudFilePathFormat = "{0}/{1}/{2}";

        public AzureBlobStorage(CloudStorageAccount cloudStorageAccount, string deploymentId, string roleName, string filename)
        {
            _cloudStorageAccount = cloudStorageAccount;
            this._deploymentId = deploymentId;
            this._roleName = roleName;
            this._filename = filename;
        }

        public bool ShouldCommit()
        {
            var blob = GetFluentBlob();

            try
            {
                string existingFile = blob.DownloadText();
                return !DocumentContainsDeploymentId(existingFile, _deploymentId);
            }
            catch
            {
                return true;//any exception on downloading a blob (i.e. 404) should result in an attempt to commit
            }

            return false;
        }

        public bool DocumentContainsDeploymentId(string existingFile, string deploymentId)
        {
            XDocument fileParsed = XDocument.Parse(existingFile);
            return fileParsed.Root.Descendants("deployment").Any(
                t => t.Value.Equals(deploymentId, StringComparison.InvariantCultureIgnoreCase));
        }

        public void PutFluentMarker()
        {
            var blob = GetFluentBlob();

            string existingFile = string.Empty;
            try
            {
                existingFile = blob.DownloadText();
            }
            catch
            {
                //the blob may not work
            }

            if (string.IsNullOrEmpty(existingFile))
            {
                blob.UploadText(GetXmlFluentFile(_deploymentId));
            }
            else
            {
                blob.UploadText(AddXmlFluentItem(existingFile, _deploymentId));
            }

        }

        private CloudBlob GetFluentBlob()
        {
            var blobClient = _cloudStorageAccount.CreateCloudBlobClient();

            var container = blobClient.GetContainerReference(CloudContainerName);
            container.CreateIfNotExist();

            var blob = container.GetBlobReference(string.Format(CloudFilePathFormat, _deploymentId, _roleName, _filename));
            return blob;
        }

        public string AddXmlFluentItem(string existingFile, string deploymentId)
        {
            XDocument xDocument = XDocument.Parse(existingFile);
            xDocument.Root.Descendants("deployments").First().Add(new XElement("deployment", deploymentId));
            return xDocument.ToString();
        }
        
        public string GetXmlFluentFile(string deploymentId)
        {
            XDocument xDocument = XDocument.Parse("<fluent><deployments/></fluent>");
            xDocument.Root.Descendants("deployments").First().Add(new XElement("deployment", deploymentId));
            return xDocument.ToString();
        }
    }
}